package jwt

import (
	"context"
	"errors"
	"github.com/dgrijalva/jwt-go"
	"jy_go/common"
	Config "jy_go/config"
	redis2 "jy_go/jy_redis"
	"strconv"
	"time"
)

type Claims struct {
	jwt.StandardClaims
	AdminId uint
	Autograph string
}

var (
	redis 	= redis2.GetRedis()
	ctx 	= context.Background()
)

//颁发token
func GetToken(AdminId uint,JwtKey []byte) (string,error) {

	claims := Claims{
		AdminId: AdminId,
		Autograph: common.GetRandomString(5),
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: time.Now().Add(3 * 24 * time.Hour).Unix(), //过期时间 3天
			IssuedAt:  time.Now().Unix(),
			Issuer:    Config.Config("config","Config","ip"),  // 签名颁发者
			Subject:   Config.Config("config","Config","sub"), //签名主题
		},
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

	tokenString, err := token.SignedString(JwtKey)
	if err != nil {

		return "",errors.New("token生成失败")
	}
	redis.Set(ctx,"admin"+strconv.Itoa(int(claims.AdminId)),claims.Autograph,24 * time.Hour)
	return tokenString,nil
}

//解析token
func AnalysisToken(tokenString string,JwtKey []byte) (uint,error) {
	if tokenString == "" {
		return 0, errors.New("token不能为空")
	}

	token, claims, err := ParseToken(tokenString,JwtKey)
	if err != nil || !token.Valid {
		return 0,errors.New("token无效,请重新登录")
	}
	if !VerificationTokenTime("admin" + strconv.Itoa(int(claims.AdminId)),claims.Autograph) {
		return 0,errors.New("token无效,请重新登录")
	}
	return claims.AdminId,nil
}

//验证token时间是否有效
func VerificationTokenTime(name string,value string) bool {
	val := redis.Get(ctx,name).Val()
	if val != "" && val == value {
		redis.Set(ctx,name,value,24 * time.Hour)
		return true
	}
	return false
}

//验证签名
func ParseToken(tokenString string,JwtKey []byte) (*jwt.Token, *Claims, error) {
	Claims := &Claims{}
	token, err := jwt.ParseWithClaims(tokenString, Claims, func(token *jwt.Token) (i interface{}, err error) {
		return JwtKey, nil
	})
	return token, Claims, err
}
